package cn.yzj.openapi.dao.impl;

import cn.yzj.openapi.basic.SecretShortUrl;
import cn.yzj.openapi.converter.ShortUrlConverter;
import cn.yzj.openapi.dao.base.ShortUrlBaseDao;
import cn.yzj.openapi.dao.intf.ShortUrlDao;
import cn.yzj.openapi.dto.UrlDTO;
import cn.yzj.openapi.entity.ShortUrlEntity;
import cn.yzj.openapi.enums.error.ShortUrlErrorEnums;
import cn.yzj.openapi.exception.OpenApiException;
import cn.yzj.openapi.mapper.ShortUrlMapper;
import cn.yzj.openapi.utils.DateUtils;
import cn.yzj.openapi.utils.StrUtils;
import cn.yzj.openapi.utils.UrlOperaUtils;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Repository;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;

/**
 * ShortUrlDaoImpl: 数据操作接口实现
 *
 * <p>这只是一个减少手工创建的模板文件 可以任意添加方法和实现, 更改作者和重定义类名
 *
 * @author gzkemays
 */
@Repository
public class ShortUrlDaoImpl extends ShortUrlBaseDao implements ShortUrlDao {
  @Resource ShortUrlMapper urlMapper;
  @Resource HttpServletResponse response;
  ShortUrlConverter urlConverter = ShortUrlConverter.INSTANCE;

  @Override
  public String generateShortUrl(UrlDTO dto) {
    String url = dto.getUrl();
    if (!StrUtils.isWeb(url)) {
      throw OpenApiException.shortUrlException(ShortUrlErrorEnums.NO_WEB);
    }
    ShortUrlEntity query = urlMapper.findOne(super.query().where.originUrl().eq(url).end());
    if (query == null) {
      SecretShortUrl bo = UrlOperaUtils.generateShortUrl(url);
      ShortUrlEntity shortUrlEntity = urlConverter.convertEntityBySecretShortUrlBo(bo);
      shortUrlEntity.setExpireTime(DateUtils.getDayBeforeTimeStamp(7));
      shortUrlEntity.setEnabled(true);
      urlMapper.insert(shortUrlEntity);
      return bo.getShortUrl();
    } else {
      return query.getShortUrl();
    }
  }

  @Override
  public void getOriginUrl(String shortUrl) {
    ShortUrlEntity entity =
        urlMapper.findOne(
            urlMapper.query().where.shortUrl().eq(shortUrl).and.enabled().isTrue().end());
    checkUrl(entity);
    try {
      String originUrl = entity.getOriginUrl();
      if (cn.yzj.utils.StrUtils.isChinese(originUrl)) {
        originUrl = cn.yzj.utils.StrUtils.chineseUrlEncoder(originUrl);
      }
      if (!originUrl.contains("http")) {
        originUrl = "http://" + originUrl;
      }
      response.setStatus(HttpStatus.PERMANENT_REDIRECT.value());
      response.sendRedirect(originUrl);
    } catch (IOException e) {
      e.printStackTrace();
    }
  }

  /**
   * 校验链接状态
   *
   * @param entity 短链接对象
   */
  private void checkUrl(ShortUrlEntity entity) {
    if (entity == null) {
      throw OpenApiException.shortUrlException(ShortUrlErrorEnums.EMPTY_ORIGIN);
    }
    if (!entity.getEnabled()) {
      throw OpenApiException.shortUrlException(ShortUrlErrorEnums.CLOSED_URL);
    }
    if (entity.getExpireTime().before(new Date())) {
      entity.setEnabled(false);
      urlMapper.updateById(entity);
      throw OpenApiException.shortUrlException(ShortUrlErrorEnums.OVER_TIME);
    }
    String decryptKey = UrlOperaUtils.decryptShortUrl(entity.getShortUrl(), entity.getSalt());
    if (!decryptKey.equals(entity.getKey())) {
      throw OpenApiException.shortUrlException(ShortUrlErrorEnums.CHECK_FAIL);
    }
  }
}
